﻿// FLMScanParameters
// Container for FLMScan parameters
// 
// FLMScan - Featured by FabLab Munich

using System;
using System.Text;
using System.IO;
using System.Xml;
using log4net;

namespace FLMScan.Parameters
{
    class FLMScanParameters
    {
        private ILog logger;
        private string configurationFilePath;

        private CameraSensorParameters cameraSensorParameters;
        private CameraParameters cameraParameters;
        private LaserPlaneParameters laserPlaneParameters;
        private RotationAxisParameters rotationAxisParameters;

        private String uiLanguage;
        private int calibrationPlaneX;
        private int calibrationPlaneY;
        private string laserColor;
        private int arduinoSerialPort;
        private string temporaryFolder;
        private string filePrefix;
        private string logConfig;

        private const String UILanguageParameter = "UILanguage";        
        private const String CalibrationPlaneXParameter = "CalibrationPlaneX";
        private const String CalibrationPlaneYParameter = "CalibrationPlaneY";
        private const String LaserColorParameter = "LaserColor";
        private const String ArduinoSerialPortParameter = "ArduinoSerialPort";   
        private const String TemporaryFolderParameter = "TemporaryFolder";           
        private const String FilePrefixParameter = "FilePrefix";       
        private const String LogConfigParameter = "LogConfig";               

        private const String ConfigurationFilePathPostfix = @"\Config\FlmScan.exe.config";
        private const String ConfigurationFileBackupPostfix = "_backup";

        private const String LogReadingParametersFromConfigFile = "Reading parameters from configuration file ";
        
        internal const String LogSettingParameterToValue = "Setting parameter {0} to value {1}";
        internal const String LogExceptionReadingParametersFromConfigFile = "Exception while reading parameters from config file: ";

        public FLMScanParameters(string currentPath)
        {
            logger = LogManager.GetLogger(typeof(FLMScanParameters));

            configurationFilePath = currentPath + ConfigurationFilePathPostfix;

            logger.Debug( LogReadingParametersFromConfigFile + configurationFilePath);

            Initialize(configurationFilePath);

            cameraParameters = new CameraParameters(configurationFilePath);
            cameraSensorParameters = new CameraSensorParameters(configurationFilePath);            
            rotationAxisParameters = new RotationAxisParameters(configurationFilePath);
            laserPlaneParameters = new LaserPlaneParameters(configurationFilePath);
        }

        public CameraSensorParameters CameraSensorParameters
        {
            get { return cameraSensorParameters; }
        }

        public CameraParameters CameraParameters
        {
            get { return cameraParameters; }
        }

        public LaserPlaneParameters LaserPlaneParameters
        {
            get { return laserPlaneParameters; }
        }

        public RotationAxisParameters RotationAxisParameters
        {
            get { return rotationAxisParameters; }
        }

        public string UiLanguage
        {
            get { return uiLanguage; }
            set { uiLanguage = value; }
        }

        public int CalibrationPlaneX
        {
            get { return calibrationPlaneX; }
            set { calibrationPlaneX= value; }
        }

        public int CalibrationPlaneY
        {
            get { return calibrationPlaneY; }
            set { calibrationPlaneY = value; }
        }

        public string LaserColor
        {
            get { return laserColor; }
            set { laserColor = value; }
        }

        public int ArduinoSerialPort
        {
            get { return arduinoSerialPort; }
            set { arduinoSerialPort = value; }
        }

        public string TemporaryFolder
        {
            get { return temporaryFolder; }
            set { temporaryFolder = value; }
        }

        public string FilePrefix
        {
            get { return filePrefix; }
            set { filePrefix= value; }
        }

        public string LogConfig
        {
            get { return logConfig; }
            set { logConfig = value; }
        }

        public void Serialize()
        {
            // back up old configuration file
            String backupConfigurationFilePath = configurationFilePath + ConfigurationFileBackupPostfix;

            if(File.Exists(backupConfigurationFilePath))
            {
                try
                {
                    File.Delete(backupConfigurationFilePath);
                }
                catch(System.Exception)
                {
                    // TBD: handle this
                }
            }

            if(File.Exists(configurationFilePath))
            {
                try
                {
                    File.Copy(configurationFilePath, backupConfigurationFilePath);
                }
                catch(System.Exception)
                {
                    // TBD: handle this
                }
            }

            //StringBuilder stringBuilder = new StringBuilder();
            //XmlWriterSettings writerSettings = new XmlWriterSettings();
            //writerSettings.Indent = true;
            //writerSettings.IndentChars = "  ";
            //writerSettings.NewLineChars = "\r\n";
            //writerSettings.NewLineHandling = NewLineHandling.Replace;            
            XmlTextWriter textWriter = new XmlTextWriter(configurationFilePath, Encoding.Unicode);
            textWriter.Formatting = Formatting.Indented;
            textWriter.Indentation = 4;            
            
            textWriter.WriteStartDocument();
            textWriter.WriteStartElement("configuration");
            textWriter.WriteStartElement("appSettings");

            SerializeParameters(textWriter);
            cameraParameters.Serialize(textWriter);
            cameraSensorParameters.Serialize(textWriter);
            rotationAxisParameters.Serialize(textWriter);
            laserPlaneParameters.Serialize(textWriter);

            textWriter.WriteEndElement();
            textWriter.WriteEndElement();
            textWriter.WriteEndDocument();
            textWriter.Close();
        }

        public static void SerializeParameter(XmlTextWriter textWriter, String name, String value)
        {
            textWriter.WriteStartElement("add");
            textWriter.WriteAttributeString(name, value);
            textWriter.WriteEndElement();
        }

        private void SerializeParameters(XmlTextWriter textWriter)
        {
            SerializeParameter(textWriter, UILanguageParameter, UiLanguage);
            SerializeParameter(textWriter, CalibrationPlaneXParameter, CalibrationPlaneX.ToString());
            SerializeParameter(textWriter, CalibrationPlaneYParameter, CalibrationPlaneY.ToString());
            SerializeParameter(textWriter, LaserColorParameter, LaserColor);
            SerializeParameter(textWriter, ArduinoSerialPortParameter, ArduinoSerialPort.ToString());
            SerializeParameter(textWriter, TemporaryFolderParameter, TemporaryFolder);
            SerializeParameter(textWriter, FilePrefixParameter, FilePrefix);
            SerializeParameter(textWriter, LogConfigParameter, LogConfig);
        }        

        private void Initialize(string configFilePath)
        {
            SetDefaultValues();

            try
            {
                TextReader reader = new StreamReader(configFilePath);
                GetConfigValues(reader);
            }
            catch (FileNotFoundException)
            {
                // TBD throw exception
            }
        }       

        private void SetDefaultValues()
        {
            // TBD: set default values here
        }

        private void GetConfigValues(TextReader reader)
        {
            XmlTextReader xmlReader = new XmlTextReader(reader);
            while (xmlReader.Read())
            {
                if (xmlReader.NodeType == XmlNodeType.Element &&
                    xmlReader.Name.Equals("add") &&
                    xmlReader.MoveToNextAttribute())
                {
                    try
                    {
                        switch (xmlReader.Name)
                        {
                            case UILanguageParameter:
                                UiLanguage = xmlReader.Value;
                                logger.DebugFormat(LogSettingParameterToValue, UILanguageParameter, UiLanguage);
                                break;
                            case CalibrationPlaneXParameter:
                                CalibrationPlaneX = int.Parse(xmlReader.Value);
                                logger.DebugFormat(LogSettingParameterToValue, CalibrationPlaneXParameter, CalibrationPlaneX);
                                break;
                            case CalibrationPlaneYParameter:
                                CalibrationPlaneY = int.Parse(xmlReader.Value);
                                logger.DebugFormat(LogSettingParameterToValue, CalibrationPlaneYParameter, CalibrationPlaneY);
                                break;
                            case LaserColorParameter:
                                LaserColor = xmlReader.Value;
                                logger.DebugFormat(LogSettingParameterToValue, LaserColorParameter, LaserColor);
                                break;
                            case ArduinoSerialPortParameter:
                                ArduinoSerialPort = int.Parse(xmlReader.Value);
                                logger.DebugFormat(LogSettingParameterToValue, ArduinoSerialPortParameter, ArduinoSerialPort);
                                break;
                            case TemporaryFolderParameter:
                                TemporaryFolder = xmlReader.Value;
                                logger.DebugFormat(LogSettingParameterToValue, TemporaryFolderParameter, TemporaryFolder);
                                break;
                            case FilePrefixParameter:
                                FilePrefix = xmlReader.Value;
                                logger.DebugFormat(LogSettingParameterToValue, FilePrefixParameter, FilePrefix);
                                break;
                            case LogConfigParameter:
                                LogConfig = xmlReader.Value;
                                logger.DebugFormat(LogSettingParameterToValue, LogConfigParameter, LogConfig);
                                break;
                        }
                    }
                    catch(System.Exception e)
                    {
                        System.Diagnostics.Debug.Assert(false, e.ToString());
                        logger.Error(LogExceptionReadingParametersFromConfigFile, e);
                    }
                }
            }

            xmlReader.Close();
        }
    }
}
